#include "common.hpp"

static const char *optString = "r:h?";

static const struct option longOpts[] = {
	{ "help", no_argument, NULL, 'h' },
	{ "resource", required_argument, NULL, 'r' },
	{ 0,0,0,0 }
};

int main (int argc, char* const argv[]) {

	ipc::semaphore_with_exceptions mutex_transportadoraA ( my_ftok(MUTEX|TRANSPORTADORA_A),0 );
	ipc::semaphore_vector mutex_llenadoras ( my_ftok(MUTEX|LLENADORA),MAX_LLENADORAS );

	ipc::messages_queue_with_exceptions transportadoraA_salida ( my_ftok(MSG_QUEUE|TRANSPORTADORA_A) );

	int longIndex = 0;
	int option = 0;
	bool ayuda = false;
	bool seguir = true;
	int botellas = 0;
	size_t enviadas = 0;

	// Interpretación de parametros.
	while ( (option = getopt_long(argc,argv,optString,longOpts,&longIndex) ) != EOF ) {
		switch (option) {
			case '?':
			case 'h':
			case ':':
				ayuda = true;
				break;
			case 'r':
				botellas = parse<int>(optarg,0);
				break;
			default:
				break;
		}
	}

	if ( ayuda || botellas < 0) {
		std::cerr << "Proceso de control de envio de botellas a las llenadoras." << std::endl;
		std::cerr << "\tUso: " << argv[0] << " [-h] [-r natural]" << std::endl;
		std::cerr << "\tParametros:" << std::endl;
		std::cerr << "\t\t-h,--help:\tMostrar este mensaje de ayuda." << std::endl;
		std::cerr << "\t\t-r,--resource:\tCantidad de botellas vacias disponibles." << std::endl;
		return (ayuda) ? 0 : -1;
	}

	sPedido pedido;
	pedido.tipo = CUALQUIERA;
	pedido.recurso = NINGUNO;

	sBotella vacia;
	vacia.tipo = SBOTELLA_TIPO;
	vacia.estado = VACIA;

	try {
		mutex_transportadoraA.get(PERMITS);
		mutex_llenadoras.get(PERMITS);
	
		transportadoraA_salida.get(PERMITS);
	
		logger <<  "Transportadora A: Inicio." << nl;
		while (seguir) {
			mutex_transportadoraA.wait();

			if (botellas > 0) {
		
				pedido.tipo = CUALQUIERA;
				transportadoraA_salida.receive(pedido,SRECURSO_TIPO);

				if ( (pedido.tipo == SRECURSO_TIPO) && (pedido.recurso == BOTELLA) ) {
					int index = pedido.estacion - SESTACION_0;

					if ( (index >= 0) && (index < MAX_LLENADORAS) ) {
						// Envio la botella y reactivo la llenadora.
						botellas--;
						enviadas++;
						logger << "Transportadora A: Enviando botella " << enviadas << "." << nl;

						transportadoraA_salida.send(vacia);
						mutex_llenadoras.signal(index);
					} else {
						error << "Pedido de una llenadora inexistente: Llenadora " << index << "." << nl;
					}
				} else {
					error << "Transportadora A: Ignorando pedido incorrecto." << nl;
				}
				mutex_transportadoraA.signal();
			} else {
				logger << "Transportadora A: Detenida por falta de botellas vacias." << nl;
			}
		}
	} catch (ipc::exception& e) {
		logger << "Transportadora A: " << e.what() << "." << nl;
		exit(-1);
	}
	logger << "Transportadora A: Fin." << nl;
	return 0;
}
